Skip to content

tnctl bootstrap: node roles for robots with several computers - #21

Merged
tekn0ir merged 2 commits into
mainfrom
nextgen
Oct 16, 2026
Merged

tekn0ir merged 2 commits into
mainfrom
nextgen

Conversation

@tekn0ir

@tekn0ir tekn0ir commented Oct 16, 2026

Copy link
Copy Markdown
Contributor

Node roles are k3s node labels, and k3s applies node-label / node-taint only when a computer registers, so the role is chosen at bootstrap (Anders: "the node role has to be chosen at bootstrap, right? So there might be changes to tnctl to do first").

What

  • New flags on tnctl bootstrap: --robot, --role, --node-name, repeatable --label and --taint for the server script; --agent-role, --agent-node-name, --agent-label, --agent-taint for the agent script from the same run (one run = one shared k3s token); --server <host> (bakes K3S_URL into the agent script and adds the host to the server's --tls-san); repeatable --tls-san.
  • Labels teknoir.org/node-role, teknoir.org/robot and extras go to a drop-in /etc/rancher/k3s/config.yaml.d/98-teknoir-node.yaml (node-label+ / node-taint+, never overwriting the owner's lists); node-name goes into config.yaml only if absent. An already-registered node gets a warning with the kubectl command to apply the labels.
  • kubernetes.io/ and k8s.io/ keys refused (NodeRestriction).
  • docs/commands/bootstrap.md: "Robots with several computers".

Checks

🤖 Generated with Claude Code

tekn0ir and others added 2 commits October 16, 2026 19:12
The role of a computer in a robot is a set of k3s node labels, and k3s applies
node-label/node-taint only when a node registers, so it has to be chosen at
bootstrap.

- New flags: --robot, --role, --node-name, --label, --taint (server script),
  --agent-role/--agent-node-name/--agent-label/--agent-taint (agent script),
  --server (K3S_URL=https://<host>:6443 in the agent script, env still wins;
  also a TLS SAN of the server) and --tls-san. One run still produces server
  and agent scripts with one token. Values are validated (DNS labels, label
  and taint syntax); the kubernetes.io/ and k8s.io/ prefixes are refused.
- New scripts/tn-k3s-node.sh, embedded only when a node flag is given: writes
  node-name to config.yaml when absent, and node-label+/node-taint+ to the
  drop-in config.yaml.d/98-teknoir-node.yaml (atomic, rewritten only when it
  differs, never touches keys the owner set). On a node that has registered
  already it warns and prints the kubectl label/taint commands.
- Without the new flags the scripts are byte-identical (existing goldens).
- Tests: validation, rendering, new roles goldens for server and agent, shell
  tests that run the config writer twice against a temp dir.
- docs/commands/bootstrap.md: "Robots with several computers".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One conflict, in cmd/bootstrap.go: main added templates.ValidateTemplateData(data)
right before the generate closure; nextgen turned that spot into
nodes.apply(data) (server and agent get their own TemplateData) and a generate
closure that takes the data. Resolution: validate the base data first (as on
main, same error text), then apply the node options, then generate with the
per-script data. The node fields are validated again in Render.

The rest merged cleanly and was checked:
- The scripts generated without the node flags are byte-identical to main (the
  server, agent and docker_server goldens are main's).
- Main keeps the k3s token of a k3s that has started (keep-k3s-token block, which
  rewrites only "--token <generated>" in INSTALL_K3S_EXEC). The nextgen --server /
  --tls-san SANs are part of the same INSTALL_K3S_EXEC and survive it; new test
  TestReRunKeepsTheExistingK3sTokenWithNodeFlags covers it. The node drop-in
  (tn-k3s-node.sh) does not depend on the token.
- Regenerated only the role goldens (server/agent .roles.golden.sh); against the
  plain goldens they differ only by the node block, the SANs and the node-name line.
- docs/commands/bootstrap.md: states how the token behaves on re-runs with several
  computers (the agent script of a re-run carries a token the server no longer
  uses; pass K3S_TOKEN from server/token).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@tekn0ir
tekn0ir merged commit 356bc5a into main Oct 16, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant